package br.com.jk.cliente;

import br.com.jk.fornecedor.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.table.AbstractTableModel;

/**
 *
 * @author camilo
 */
public class ClienteTableModel extends AbstractTableModel {

  private static final long serialVersionUID = 1L;
  public static final int COLUNA_QTD = 13;
  public static final String COLUNA_NAME_ID = "Id";
  public static final String COLUNA_NAME_CNPJ = "CNPJ/CPF";
  public static final String COLUNA_NAME_IE = "IE/RG";
  public static final String COLUNA_NAME_RAZAO = "Nome Comp.";
  public static final String COLUNA_NAME_FANTASIA = "Nome Ab.";
  public static final String COLUNA_NAME_PFISICA = "P. Fis.";
  public static final String COLUNA_NAME_RUA = "Endereço";
  public static final String COLUNA_NAME_COMPLEMENTO = "Complemento";
  public static final String COLUNA_NAME_NUMERO = "Nº";
  public static final String COLUNA_NAME_BAIRRO = "Bairro";
  public static final String COLUNA_NAME_CIDADE = "Cidade";
  public static final String COLUNA_NAME_CEP = "CEP";
  public static final String COLUNA_NAME_OBSERVACAO = "Observação";
  public static final int COLUNA_COD_ID = 0;
  public static final int COLUNA_COD_CNPJ = 1;
  public static final int COLUNA_COD_IE = 2;
  public static final int COLUNA_COD_RAZAO = 3;
  public static final int COLUNA_COD_FANTASIA = 4;
  public static final int COLUNA_COD_PFISICA = 5;
  public static final int COLUNA_COD_RUA = 6;
  public static final int COLUNA_COD_COMPLEMENTO = 7;
  public static final int COLUNA_COD_NUMERO = 8;
  public static final int COLUNA_COD_BAIRRO = 9;
  public static final int COLUNA_COD_CIDADE = 10;
  public static final int COLUNA_COD_CEP = 11;
  public static final int COLUNA_COD_OBSERVACAO = 12;
  public static final int COLUNA_COD_ID_ENDERECO = 13;
  public static final int COLUNA_COD_ID_CIDADE = 14;
  /**
   * Essa lista armazenará os objetos atualmente exibidos na tabela.
   */
  private List<Cliente> lstForn;

  /**
   * Constutor que simplesmente instancia o nosso {@link List} que usaremos para guardar os valores.
   */
  public ClienteTableModel() {
    // no construtor, instanciamos o List  
    lstForn = new ArrayList<>();
  }

  /**
   * Criamos um construtor de conveniência para já popular a lista.
   *
   * @param lista a lista de produtos a ser adicionada.
   */
  public ClienteTableModel(List<Cliente> lista) {
    this();
    lstForn.addAll(lista);
  }

  // ==============================================================  
  // Métodos implementados.  
  // ==============================================================  
  /**
   * Aqui configura-se o tipo de dados que serão apresentados por coluna
   *
   * Use o código abaixo para definir todas as colunas com o mesmo tipo de dados.<br /><br />
   * <i>return "TIPO".class;</i>
   *
   * @param coluna
   * @return
   */
  @Override
  public Class<?> getColumnClass(int coluna) {
    if (coluna == COLUNA_COD_PFISICA) {
      return Boolean.class;
    } else {
      return String.class;
    }
  }

  /**
   * Retorna a quantidade de colunas da tabela.
   *
   * @return
   */
  @Override
  public int getColumnCount() {
    return COLUNA_QTD;
  }

  /**
   * Retorna o nome de cada coluna
   *
   * @param coluna
   * @return
   */
  @Override
  public String getColumnName(int coluna) {
    switch (coluna) {
      case COLUNA_COD_ID:
        return COLUNA_NAME_ID;
      case COLUNA_COD_CNPJ:
        return COLUNA_NAME_CNPJ;
      case COLUNA_COD_IE:
        return COLUNA_NAME_IE;
      case COLUNA_COD_RAZAO:
        return COLUNA_NAME_RAZAO;
      case COLUNA_COD_FANTASIA:
        return COLUNA_NAME_FANTASIA;
      case COLUNA_COD_PFISICA:
        return COLUNA_NAME_PFISICA;
      case COLUNA_COD_RUA:
        return COLUNA_NAME_RUA;
      case COLUNA_COD_COMPLEMENTO:
        return COLUNA_NAME_COMPLEMENTO;
      case COLUNA_COD_NUMERO:
        return COLUNA_NAME_NUMERO;
      case COLUNA_COD_BAIRRO:
        return COLUNA_NAME_BAIRRO;
      case COLUNA_COD_CIDADE:
        return COLUNA_NAME_CIDADE;
      case COLUNA_COD_CEP:
        return COLUNA_NAME_CEP;
      case COLUNA_COD_OBSERVACAO:
        return COLUNA_NAME_OBSERVACAO;
      default:
        return "";
    }
  }

  /**
   * Retorna a quantidade de linhas da tabela.
   *
   * @return
   */
  @Override
  public int getRowCount() {
    return lstForn.size();
  }

  /**
   * Retorna o valor de determinada célula.
   *
   * @param linha
   * @param coluna
   * @return
   */
  @Override
  public Object getValueAt(int linha, int coluna) {
//    Cria-se um objeto com base na linha solicitada
    Cliente forn = lstForn.get(linha);

    switch (coluna) {
      case COLUNA_COD_ID:
        return forn.getId();
      case COLUNA_COD_CNPJ:
        return forn.getCnpj();
      case COLUNA_COD_IE:
        return forn.getIe();
      case COLUNA_COD_RAZAO:
        return forn.getRazao();
      case COLUNA_COD_FANTASIA:
        return forn.getFantasia();
      case COLUNA_COD_PFISICA:
        return forn.getpFisica();
      case COLUNA_COD_RUA:
        return forn.getEndereco().getRua();
      case COLUNA_COD_COMPLEMENTO:
        return forn.getEndereco().getComplemento();
      case COLUNA_COD_NUMERO:
        return forn.getEndereco().getNumero();
      case COLUNA_COD_BAIRRO:
        return forn.getEndereco().getBairro();
      case COLUNA_COD_CIDADE:
        return forn.getEndereco().getCidade().getDescricao();
      case COLUNA_COD_CEP:
        return forn.getEndereco().getCep();
      case COLUNA_COD_OBSERVACAO:
        return forn.getEndereco().getObservacao();
      case COLUNA_COD_ID_ENDERECO:
        return forn.getEndereco().getId(); //retorna o id do endereço
      case COLUNA_COD_ID_CIDADE:
        return forn.getEndereco().getCidade().getId(); //retorna o id da cidade
      default:
        return null; // não ocorrerá devido a quantidade de colunas
    }
  }

  /**
   * Define as células que poderão ser editadas.
   *
   * @param rowIndex
   * @param columnIndex
   * @return
   */
  @Override
  public boolean isCellEditable(int rowIndex, int columnIndex) {
    // nesse caso, todas as células são editáveis  
    return false;
  }

  /**
   * Define o valor para a célula da tabela
   *
   * @param valor - Novo valor para a célula
   * @param linha - Linha onde está a célula a ser alterada
   * @param coluna Coluna onde está a célula a ser alterada
   */
  @Override
  public void setValueAt(Object valor, int linha, int coluna) {
//    Cria-se um objeto com base na linha solicitada
    Cliente forn = lstForn.get(linha);
//verifica-se qual será a coluna a ser alterada
    switch (coluna) {
      case COLUNA_COD_ID:
        forn.setId(Integer.parseInt(valor.toString()));
        break;
      case COLUNA_COD_CNPJ:
        forn.setCnpj(valor.toString());
        break;
      case COLUNA_COD_IE:
        forn.setIe(valor.toString());
        break;
      case COLUNA_COD_RAZAO:
        forn.setRazao(valor.toString());
        break;
      case COLUNA_COD_FANTASIA:
        forn.setFantasia(valor.toString());
        break;
      case COLUNA_COD_PFISICA:
        forn.setpFisica(Boolean.parseBoolean(valor.toString()));
        break;
      case COLUNA_COD_RUA:
        forn.getEndereco().setRua(valor.toString());
        break;
      case COLUNA_COD_COMPLEMENTO:
        forn.getEndereco().setComplemento(valor.toString());
        break;
      case COLUNA_COD_NUMERO:
        forn.getEndereco().setNumero(valor.toString());
        break;
      case COLUNA_COD_BAIRRO:
        forn.getEndereco().setBairro(valor.toString());
        break;
      case COLUNA_COD_CIDADE:
        forn.getEndereco().getCidade().setDescricao(valor.toString());
        break;
      case COLUNA_COD_CEP:
        forn.getEndereco().setCep(Integer.parseInt(valor.toString()));
        break;
      case COLUNA_COD_OBSERVACAO:
        forn.getEndereco().setObservacao(valor.toString());
        break;
    }

    // é importante notificar os listeners a cada alteração  
    fireTableDataChanged();
  }

  // ==============================================================  
  // Até aqui seria o mínimo necessário para um TableModel funcional, mas  
  // ainda não há métodos para adicionar, remover ou resgatar objetos. Vamos  
  // criá-los.  
  // ==============================================================  
  /**
   * Similar ao {@link #adiciona()}, porém para remover. Recebe o índice do registro a ser removido. Se não
   * souber o índice, use o método {@link #getIndice()} antes.
   */
  public void remove(int indice) {
    lstForn.remove(indice);
    fireTableRowsDeleted(indice, indice);
  }

  /**
   * Retorna o índice de determinado registro.
   */
  public int getIndice(Cliente m) {
    return lstForn.indexOf(m);
  }

  /**
   * Adiciona todos os registros na lista à este modelo.
   */
  public void adicionaLista(List<?> lista) {
    int i = lstForn.size();
    lstForn.addAll((List<Cliente>) lista);
    fireTableRowsInserted(i, i + lista.size());
  }
  
    /**
   * Adiciona um novo registro e notifica os listeners que um novo registro foi adicionado.
   */
  public void adiciona(Cliente classe) {
    lstForn.add((Cliente) classe);
    // informamos os listeners que a linha (size - 1) foi adicionada  
    fireTableRowsInserted(lstForn.size() - 1, lstForn.size() - 1);
  }

  /**
   * Esvazia a lista.
   */
  public void limpaLista() {
    int i = lstForn.size();
    lstForn.clear();
    fireTableRowsDeleted(0, i - 1);
  }
}
